import math
import os

import numpy as np
from scipy.ndimage import zoom

data_save_path=r'D:\PycharmProjects\geo_classification\dataset\record\test_image'
#   函数用于设置一个长方体
def cuboid_data(center, size):
    o = [a - b / 2 for a, b in zip(center, size)]
    l, w, h = size
    x = [[o[0], o[0] + l, o[0] + l, o[0], o[0]],
         [o[0], o[0] + l, o[0] + l, o[0], o[0]],
         [o[0], o[0] + l, o[0] + l, o[0], o[0]],
         [o[0], o[0] + l, o[0] + l, o[0], o[0]]]
    y = [[o[1], o[1], o[1] + w, o[1] + w, o[1]],
         [o[1], o[1], o[1] + w, o[1] + w, o[1]],
         [o[1], o[1], o[1], o[1], o[1]],
         [o[1] + w, o[1] + w, o[1] + w, o[1] + w, o[1] + w]]
    z = [[o[2], o[2], o[2], o[2], o[2]],
         [o[2] + h, o[2] + h, o[2] + h, o[2] + h, o[2] + h],
         [o[2], o[2], o[2] + h, o[2] + h, o[2]],
         [o[2], o[2], o[2] + h, o[2] + h, o[2]]]
    return x, y, z

#计算输入坐标 xyz 与相机之间的距离
def cam_distance(x, y, z ,scene_dict):
    return np.sqrt((scene_dict['camera_loc']['x_cam'] - x) ** 2 + (scene_dict['camera_loc']['y_cam'] - y) ** 2 + (scene_dict['camera_loc']['z_cam'] - z) ** 2)

def hits_front_plane(h_angle, v_angle,scene_dict):
    y = (scene_dict['obj_loc']['xob_i'] - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(h_angle)) + scene_dict['camera_loc']['y_cam']
    z = (scene_dict['obj_loc']['xob_i'] - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    # print("{}, {}".format(y,z))
    if np.all([y <= (scene_dict['obj_loc']['yob_i'] + scene_dict['obj_loc']['Ly']), y >= scene_dict['obj_loc']['yob_i'], z <= (scene_dict['obj_loc']['zob_i'] + scene_dict['obj_loc']['Lz']), z >= scene_dict['obj_loc']['zob_i']]):
        return cam_distance(scene_dict['obj_loc']['xob_i'], y, z ,scene_dict)
    else:
        return None
def hits_left_plane(h_angle, v_angle,scene_dict):
    if h_angle == 0:
        return None
    x = (scene_dict['obj_loc']['yob_i'] - scene_dict['camera_loc']['y_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(h_angle))) / np.sin(np.deg2rad(h_angle))
    z = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    if np.all([x <= (scene_dict['obj_loc']['xob_i'] + scene_dict['obj_loc']['Lx']), x >= scene_dict['obj_loc']['xob_i'], z <= (scene_dict['obj_loc']['zob_i'] + scene_dict['obj_loc']['Lz']), z >= scene_dict['obj_loc']['zob_i']]):
        return cam_distance(x, scene_dict['obj_loc']['yob_i'], z ,scene_dict)
    else:
        return None
def hits_right_plane(h_angle, v_angle,scene_dict):
    if h_angle == 0:
        return None
    x = (scene_dict['obj_loc']['yob_i'] + scene_dict['obj_loc']['Ly'] - scene_dict['camera_loc']['y_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(h_angle))) / np.sin(np.deg2rad(h_angle))
    z = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    if np.all([x <= (scene_dict['obj_loc']['xob_i'] + scene_dict['obj_loc']['Lx']), x >= scene_dict['obj_loc']['xob_i'], z <= (scene_dict['obj_loc']['zob_i'] + scene_dict['obj_loc']['Lz']), z >= scene_dict['obj_loc']['zob_i']]):
        return cam_distance(x, scene_dict['obj_loc']['yob_i'] + scene_dict['obj_loc']['Ly'], z ,scene_dict)
    else:
        return None
def hits_top_plane(h_angle, v_angle,scene_dict):
    if v_angle == 0:
        return None
    x = (scene_dict['obj_loc']['Lz'] + scene_dict['obj_loc']['zob_i'] - scene_dict['camera_loc']['z_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(v_angle))) / np.sin(np.deg2rad(v_angle))
    y = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(h_angle)) + scene_dict['camera_loc']['y_cam']
    if np.all([x <= (scene_dict['obj_loc']['xob_i'] + scene_dict['obj_loc']['Lx']), x >= scene_dict['obj_loc']['xob_i'], y <= (scene_dict['obj_loc']['yob_i'] + scene_dict['obj_loc']['Ly']), y >= scene_dict['obj_loc']['yob_i']]):
        return cam_distance(x, y, scene_dict['obj_loc']['zob_i'] + scene_dict['obj_loc']['Lz'] ,scene_dict)
    else:
        return None
def hits_background(h_angle, v_angle,scene_dict):
    y = (scene_dict['wall_loc']['x_end'] - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(h_angle)) + scene_dict['camera_loc']['y_cam']
    z = (scene_dict['wall_loc']['x_end'] - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    if np.all([y <= scene_dict['wall_loc']['y_end'], y >= -scene_dict['wall_loc']['y_end'], z <= scene_dict['wall_loc']['z_end'], z >= -scene_dict['wall_loc']['z_end']]):
        return cam_distance(scene_dict['wall_loc']['x_end'], y, z ,scene_dict)
    else:
        return None
def hits_left_wall(h_angle, v_angle,scene_dict):
    if h_angle == 0:
        return None
    x = (-scene_dict['wall_loc']['y_end'] - scene_dict['camera_loc']['y_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(h_angle))) / np.sin(np.deg2rad(h_angle))
    z = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    if np.all([x <= scene_dict['wall_loc']['x_end'], x >= 0, z <= scene_dict['wall_loc']['z_end'], z >= -scene_dict['wall_loc']['z_end']]):
        return cam_distance(x, -scene_dict['wall_loc']['y_end'], z ,scene_dict)
    else:
        return None
def hits_right_wall(h_angle, v_angle,scene_dict):
    if h_angle == 0:
        return None
    x = (scene_dict['wall_loc']['y_end'] - scene_dict['camera_loc']['y_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(h_angle))) / np.sin(np.deg2rad(h_angle))
    z = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(v_angle)) + scene_dict['camera_loc']['z_cam']
    if np.all([x <= scene_dict['wall_loc']['x_end'], x >= 0, z <= scene_dict['wall_loc']['z_end'], z >= -scene_dict['wall_loc']['z_end']]):
        return cam_distance(x, scene_dict['wall_loc']['y_end'], z ,scene_dict)
    else:
        return None
def hits_floor(h_angle, v_angle,scene_dict):
    # can never hit the side with 0 vertical angle. prevents div by 0 error
    if v_angle == 0:
        return None
    x = (-scene_dict['wall_loc']['z_end'] - scene_dict['camera_loc']['z_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(v_angle))) / np.sin(np.deg2rad(v_angle))
    y = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(h_angle)) + scene_dict['camera_loc']['y_cam']
    if np.all([x <= scene_dict['wall_loc']['x_end'], x >= 0, y <= scene_dict['wall_loc']['y_end'], y >= -scene_dict['wall_loc']['y_end']]):
        return cam_distance(x, y, scene_dict['wall_loc']['z_end'] ,scene_dict)
    else:
        return None
def hits_ceiling(h_angle, v_angle,scene_dict):
    if v_angle == 0:
        return None
    x = (scene_dict['wall_loc']['z_end'] - scene_dict['camera_loc']['z_cam'] + scene_dict['camera_loc']['x_cam'] * np.sin(np.deg2rad(v_angle))) / np.sin(np.deg2rad(v_angle))
    y = (x - scene_dict['camera_loc']['x_cam']) * np.sin(np.deg2rad(h_angle)) + scene_dict['camera_loc']['y_cam']
    if np.all([x <= scene_dict['wall_loc']['x_end'], x >= 0, y <= scene_dict['wall_loc']['y_end'], y >= -scene_dict['wall_loc']['y_end']]):
        d=scene_dict['wall_loc']['z_end']
        return cam_distance(x, y, d ,scene_dict)
    else:
        return None
def compute_distance(h_angle, v_angle ,scene_dict):
    if hits_front_plane(h_angle, v_angle ,scene_dict) is not None:
        d = hits_front_plane(h_angle, v_angle ,scene_dict)
    elif hits_left_plane(h_angle, v_angle ,scene_dict) is not None:
        d = hits_left_plane(h_angle, v_angle ,scene_dict)
    elif hits_right_plane(h_angle, v_angle ,scene_dict) is not None:
        d = hits_right_plane(h_angle, v_angle ,scene_dict)
    elif hits_background(h_angle, v_angle ,scene_dict) is not None:
        d = hits_background(h_angle, v_angle ,scene_dict)
    elif hits_left_wall(h_angle, v_angle ,scene_dict) is not None:
        d = hits_left_wall(h_angle, v_angle ,scene_dict)
    elif hits_right_wall(h_angle, v_angle ,scene_dict) is not None:
        d = hits_right_wall(h_angle, v_angle ,scene_dict)
    elif hits_floor(h_angle, v_angle ,scene_dict) is not None:
        d = hits_floor(h_angle, v_angle ,scene_dict)
    elif hits_ceiling(h_angle, v_angle ,scene_dict) is not None:
        d = hits_ceiling(h_angle, v_angle ,scene_dict)
    else:
        d = 0

    return d


# res = 80x80
def max_depth( scene_dict):
    h_span = 160
    v_span = 160
    angle_res = 2
    tof_image = []
    for va in np.arange(v_span / 2, -v_span / 2, -angle_res):
        row = []
        for ha in np.arange(-h_span / 2 + 20, h_span / 2 + 20, angle_res):
            row.append(compute_distance(ha, va ,scene_dict))
        tof_image.append(row)
    tof_image = np.vstack(tof_image)
    maximum_depth = np.max(tof_image)
    return maximum_depth
def tof_photo(scene_dict):
    h_span = 160
    v_span = 160
    angle_res = 2
    max_dep=max_depth(scene_dict)
    tof_image = []
    for va in np.arange(v_span / 2, -v_span / 2, -angle_res):
        row = []
        for ha in np.arange(-h_span / 2 + 20, h_span / 2 + 20, angle_res):  # +20° on the right to view the room better
            row.append(compute_distance(ha, va ,scene_dict))
        tof_image.append(row)
    tof_image = np.vstack(tof_image)
    tof_image = tof_image / max_dep
    return tof_image

def arr_gen(xob_i,yob_i,zob_i,n_n,n_phot,max_count,theta0,phi0,rw,ro,l,scene_dict):
    n_scat_max = n_n + 1

    # arr_time ，大小与本次光子数相同的零矩阵 用于储存不同光子的到达时间
    arr_time = np.zeros(n_phot)

    # 该层开始对每一个光子数进行循环，得到该条件下的时间直方图
    for m in range(n_phot):
        x_photo_pos_i = scene_dict['sensor_loc']['x_sens_i']
        y_photo_pos_i = scene_dict['sensor_loc']['y_sens_i']
        z_photo_pos_i = scene_dict['sensor_loc']['z_sens_i']
        count = 0
        n_scat = 0
        extinction = False
        theta = theta0[m]
        phi = phi0[m]

        # while中的 break 会跳出 while 循环，而不会跳出for循环
        while 1:
            # 计数次数加一
            count = count + 1

            # 反射角度 因为实验中为纯镜面反射，因此统一设置为0
            scat_ang_theta = 0.0 * np.pi * (np.random.rand(1) - 0.5)
            scat_ang_phi = 0.0 * np.pi * (np.random.rand(1) - 0.5)

            # 得到最初的光子最终位置的坐标
            x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
            y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
            z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
            if all((y_photo_pos_f > scene_dict['sensor_loc']['y_sens_i'],
                    y_photo_pos_f < scene_dict['sensor_loc']['y_sens_i'] + scene_dict['sensor_loc']['sens_y'])):
                if all((z_photo_pos_f > scene_dict['sensor_loc']['z_sens_i'],
                        z_photo_pos_f < scene_dict['sensor_loc']['z_sens_i'] + scene_dict['sensor_loc']['sens_z'])):
                    if all((x_photo_pos_i > scene_dict['sensor_loc']['x_sens_i'] + scene_dict['sensor_loc']['sens_x'],
                            x_photo_pos_f < scene_dict['sensor_loc']['x_sens_i'] + scene_dict['sensor_loc']['sens_x'])):
                        break
            # Near and far wall
            if any((x_photo_pos_f > scene_dict['wall_loc']['x_end'], x_photo_pos_f < 0)):
                if np.random.rand(1) > rw:
                    extinction = True
                    break
                else:
                    theta = np.pi - theta + scat_ang_theta
                    phi = np.pi - phi + scat_ang_phi
                    x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                    y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                    z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                    n_scat = n_scat + 1
            if any((y_photo_pos_f > scene_dict['wall_loc']['y_end'], y_photo_pos_f < -scene_dict['wall_loc']['y_end'])):
                if np.random.rand(1) > rw:
                    extinction = True
                    break
                else:
                    theta = -theta + scat_ang_theta
                    phi = np.pi - phi + scat_ang_phi
                    x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                    y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                    z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                    n_scat = n_scat + 1
            if any((z_photo_pos_f > scene_dict['wall_loc']['z_end'], z_photo_pos_f < -scene_dict['wall_loc']['y_end'])):
                if np.random.rand(1) > rw:
                    extinction = True
                    break
                else:
                    theta = theta + scat_ang_theta
                    phi = -phi + scat_ang_phi
                    x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                    y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                    z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                    n_scat = n_scat + 1

                    # Object: near and front walls
            if all((y_photo_pos_f > yob_i, y_photo_pos_f < yob_i + scene_dict['obj_loc']['Ly'])):
                if all((z_photo_pos_f > zob_i, z_photo_pos_f < zob_i + scene_dict['obj_loc']['Lz'])):
                    if any((all((x_photo_pos_i < xob_i, x_photo_pos_f > xob_i)),
                            all((x_photo_pos_i > xob_i + scene_dict['obj_loc']['Lx'],
                                 x_photo_pos_f < xob_i + scene_dict['obj_loc']['Lx'])))):
                        if np.random.rand(1) > ro:
                            extinction = True
                            break
                        else:
                            theta = np.pi - theta + scat_ang_theta
                            phi = np.pi - phi + scat_ang_phi
                            x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                            y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                            z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                            n_scat = n_scat + 1

                            # Object: left and right walls
            if all((x_photo_pos_f > xob_i, x_photo_pos_f < xob_i + scene_dict['obj_loc']['Lx'])):
                if all((z_photo_pos_f > zob_i, z_photo_pos_f < zob_i + scene_dict['obj_loc']['Lz'])):
                    if any((all((y_photo_pos_i < yob_i, y_photo_pos_f > yob_i)),
                            all((y_photo_pos_i > yob_i + scene_dict['obj_loc']['Ly'],
                                 y_photo_pos_f < yob_i + scene_dict['obj_loc']['Ly'])))):
                        if np.random.rand(1) > ro:
                            extinction = True
                            break
                        else:
                            theta = -theta + scat_ang_theta
                            phi = np.pi - phi + scat_ang_phi
                            x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                            y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                            z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                            n_scat = n_scat + 1

                            # Object: top and bottom walls
            if all((x_photo_pos_f > xob_i, x_photo_pos_f < xob_i + scene_dict['obj_loc']['Lx'])):
                if all((y_photo_pos_f > yob_i, y_photo_pos_f < yob_i + scene_dict['obj_loc']['Ly'])):
                    if any((all((z_photo_pos_i < zob_i, z_photo_pos_f > zob_i)),
                            all((z_photo_pos_i > zob_i + scene_dict['obj_loc']['Lz'],
                                 z_photo_pos_f < zob_i + scene_dict['obj_loc']['Lz'])))):
                        if np.random.rand(1) > ro:
                            extinction = True
                            break
                        else:
                            theta = theta + scat_ang_theta
                            phi = -phi + scat_ang_phi
                            x_photo_pos_f = x_photo_pos_i + l * np.cos(theta)
                            y_photo_pos_f = y_photo_pos_i + l * np.sin(theta)
                            z_photo_pos_f = z_photo_pos_i + l * np.sin(phi)
                            n_scat = n_scat + 1
            # 反射次数达到最大值或者计数值达到最大 ，跳出while循环，否则将本次得到的终点坐标作为下一次光的起点坐标
            if n_scat > n_scat_max:
                break
            if count > max_count:
                break
            theta = np.arctan2((y_photo_pos_f - y_photo_pos_i), (x_photo_pos_f - x_photo_pos_i))
            x_photo_pos_i = x_photo_pos_f
            y_photo_pos_i = y_photo_pos_f
            z_photo_pos_i = z_photo_pos_f
        count = count + (1 + 0.5 * np.random.randn(1))[0]  # 向其中添加延时
        if count > max_count or n_scat > n_scat_max or extinction == True:
            arr_time[m] = float('NaN')
        else:
            arr_time[m] = count
    arr_time = arr_time[~np.isnan(arr_time)]
    return  arr_time

# 定义实现产生用于训练的虚拟数据
#   n_photon : 对于单个场景，探测所使用的光子数     max_count： 最大的测量时间      n_scat_maximum：波被吸收前所允许的最大反射数目
#   rw/ro ：墙面或物体的反射率 l : 光子的平均自由程

def data_generator(scene_dict,nx,ny,nz,max_count,n_scat_maximum,n_phot,rw=1,ro=1,l=0.2,bins=200):
    #初始化处理数 0.75是对探测角度的缩放
    processed = 0
    theta0 = 0.75 * np.pi * (np.random.rand(n_phot) - 0.5)
    phi0 = 0.75 * np.pi * (np.random.rand(n_phot) - 0.5)

    xob_list = (2 + scene_dict['sensor_loc']['sens_x']) + ((scene_dict['wall_loc']['x_end'] - scene_dict['obj_loc']['Lx']) - (0.5 + scene_dict['sensor_loc']['sens_x'])) * np.linspace(0, 1, nx)
    yob_list = 0 + ((scene_dict['wall_loc']['y_end'] - scene_dict['obj_loc']['Ly']) - (-scene_dict['wall_loc']['y_end'])) * np.linspace(0, 1, ny)
    zob_list = np.zeros(1)
    # 第一层循环，最大允许的反射数目不同，
    arr_data = np.empty((n_scat_maximum,nx*ny*nz,bins,1))
    tof_data = np.empty((n_scat_maximum,nx*ny*nz,80,80,1))
    for n_n in range(n_scat_maximum):
        print('本次最大允许反射数:',n_n)
        data_record=0
        #第二、三、四层循环 更换目标物体的位置
        for i in range(nx):
            for j in range(ny):
                for k in range(nz):
                    #xob_i yob_i zob_i ：本次循环中 目标物体的位置
                    xob_i = xob_list[i]
                    yob_i = yob_list[j]
                    zob_i = zob_list[k]

                    # 修改字典中的物体位置
                    scene_dict['obj_loc']['xob_i'] = xob_i
                    scene_dict['obj_loc']['yob_i'] = yob_i
                    scene_dict['obj_loc']['zob_i'] = zob_i

                    #arr_time ，大小与本次光子数相同的零矩阵 用于储存不同光子的到达时间
                    result=arr_gen(xob_i,yob_i,zob_i,n_n,n_phot,max_count,theta0,phi0,rw,ro,l,scene_dict)
                    result,_=np.histogram(result,bins=200)
                    result=np.reshape(result,(200,1))
                    ground_truth=np.reshape(tof_photo(scene_dict),(80,80,1))
                    tof_data[n_n,data_record,:,:,:]=ground_truth
                    arr_data[n_n,data_record,:,:]=result
                    processed   = processed   + 1
                    data_record = data_record + 1
                    print('processed', processed, 'examples')
    return arr_data,tof_data

def count_files_with_suffix(directory, suffix):
    count = 0
    # 遍历目录中的每个文件和子目录
    for root, dirs, files in os.walk(directory):
        # 遍历当前目录下的文件
        for file in files:
            if file.endswith(suffix):  # 判断文件后缀
                count += 1
    return count
def ordered_image(FOV,original_folder_path,output_folder_path,file_extension,head_name):
    # 定义一个函数，可以给一个文件夹下的指定后缀的文件重新命名并输入到新的指定文件夹下
    # 并将图像重新整理为FOV大小
    if not os.path.exists(output_folder_path):
        os.makedirs(output_folder_path)
    original_files = [f for f in os.listdir(original_folder_path) if f.endswith(file_extension)]
    original_files.sort()   #给读取到的文件名排序方便编号
    for index,file_name in enumerate(original_files):
        file_path = os.path.join(original_folder_path,file_name)
        new_file_name=f"{head_name}{index+1:04d}{file_extension}" #使用三位数字编号
        new_file_path = os.path.join(output_folder_path,new_file_name)
        with open(file_path, 'rb') as f_in:
            with open(new_file_path, 'wb') as f_out:
                f_out.write(f_in.read())
        print(f"{file_name} -> {new_file_name}")
    #到这已经完成了对文件名的重整
    #再来个for循环，将所有新文件处理
    suffix             = '.png'
    file_num           = count_files_with_suffix(output_folder_path,suffix)
    for i in range(file_num):
        file_name=f"{head_name}{i+1:04d}{file_extension}"
        file_path_ele = os.path.join(output_folder_path, file_name)
        img_load = Image.open(file_path_ele).convert('L')
        w,h = img_load.size
        max_size = max(w,h)
        new_image = Image.new("L", (max_size, max_size), color=255)
        paste_position = ((max_size - w) // 2, (max_size - h) // 2)
        # 将原始图片粘贴到新画布上
        new_image.paste(img_load, paste_position)
        # 调整图片大小为 target_size x target_size
        resized_image = new_image.resize((FOV['x_len'],FOV['y_len']), Image.Resampling.LANCZOS)
        resized_image.save(file_path_ele)

from PIL import Image
import random
import matplotlib.pyplot as plt
def original_scene_gen(element_file,mother_path,num_of_scene,max_depth,FOV,file_extension,head_name,
                       new_head_name,new_file_extension,scene_save_file,bin=200):
    output_folder_path = os.path.join(mother_path,scene_save_file)
    if not os.path.exists(output_folder_path):
        os.makedirs(output_folder_path)
    #本函数输入一个包含有场景中元素图案的文件，生成随机场景，以及相应的飞行时间数据对
    suffix             = '.png'
    file_num           = count_files_with_suffix(element_file,suffix) #得到文件中可用于制作场景的元素数据
    element_matrix     = np.zeros((file_num,num_of_scene),dtype = int)
    arr_matrix         = np.empty((num_of_scene,bin,1))
    tof_data           = np.empty((num_of_scene,FOV['x_len'],FOV['y_len'],1))
    for cols in range(num_of_scene):
        #在下一行中设置生成场景中包含的元素数目
        indices = np.random.choice(file_num,size=np.random.randint(1, 2), replace=False)
        element_matrix[indices, cols] = 1
    scene_scale_matrix = np.random.uniform(0.5,1,(file_num,num_of_scene))#深度矩阵，同时代表缩放大小
    scene_scale_matrix = np.where(element_matrix == 1,scene_scale_matrix,0) #没有使用对应元素的变为0
    row_label          = np.arange(1,file_num+1).reshape(-1,1)
    label_of_img       = row_label * element_matrix
    #按照缩放大小从近到远排列图像，排列后的值是对应的元素和对应元素缩放的大小，行是顺序的索引
    sorted_indices     = np.argsort(scene_scale_matrix,axis=0)[::-1,:]
    scene_scale_matrix = np.take_along_axis(scene_scale_matrix,sorted_indices,axis=0)
    label_of_img       = np.take_along_axis(label_of_img,sorted_indices,axis=0)
    for i in range(num_of_scene):   #遍历生成每个场景
        #生成白色背景的灰度图画布
        image_of_scene = Image.new('L',(FOV['x_len'],FOV['y_len']),255)
        image_matrix   = np.array(image_of_scene)
        for k in range(file_num):
            # k 就代表正在遍历的行数，是从0开始的 ，同时也是从最近的开始运算
            if label_of_img[k,i]!=0:
                ele_file_name = f"{head_name}{label_of_img[k,i]:04d}{file_extension}"
                file_path_ele = os.path.join(element_file,ele_file_name)
                img_load      = Image.open(file_path_ele).convert('L')
                img_width, img_height = img_load.size
                # 按照深度缩小图像
                scale       = scene_scale_matrix[k,i]
                img_width   = int(np.floor(img_width*scale))
                img_height  = int(np.floor(img_height*scale))
                resized_img = img_load.resize((img_width,img_height),Image.Resampling.LANCZOS)
                resized_img = np.array(resized_img)
                past_x=random.randint(0,FOV['x_len']-1-img_width)
                past_y=random.randint(0,FOV['y_len']-1-img_height)
                resized_img = 255-(255-resized_img)*scale

                # 将图像放到画布上，颜色越深灰度值越小，因此遍历较小值
                for x in range(img_width):
                    for y in range (img_height):
                        img_pixel_value      = resized_img[y,x]
                        y_pixel              = past_y+y
                        x_pixel              = past_x+x
                        original_pixel_value = image_matrix[y_pixel,x_pixel]
                        new_pixel_value      = int(min(img_pixel_value,original_pixel_value))
                        image_of_scene.putpixel((y_pixel,x_pixel),new_pixel_value)
                        image_matrix[y_pixel,x_pixel] = new_pixel_value
                if i<10:
                    #saved_img_name =f"{new_head_name}{i:04d}{new_file_extension}"
                    saved_jet_name = f"{new_head_name}{i:04d}{new_file_extension}"
                    #final_save_path = os.path.join(str(output_folder_path),str(saved_img_name))
                    jet_save_path   = os.path.join(str(output_folder_path),str(saved_jet_name))
                    # 使用 Matplotlib 的 jet 颜色映射
                    jet_colormap = plt.cm.get_cmap("jet")  # 获取 jet 颜色映射
                    jet_array = jet_colormap(image_matrix)  # 将灰度值映射为伪彩色
                    # 将伪彩色图像转换为 Pillow 图像
                    jet_image = Image.fromarray((jet_array[:, :, :3] * 255).astype(np.uint8))  # 提取 RGB 通道并转换为 uint8
                    # 保存或显示图像
                    jet_image.save(jet_save_path)
            else: continue       #不满足表示已经没有图像要处理，因此可以直接跳出循环
        #image_of_scene.save(final_save_path)
        background_mask = image_matrix!=255
        # image_matrix是ndarray格式的数据，因此可以对它进行处理
        x_position_matrix = np.tile(np.arange(FOV['y_len']),(FOV['x_len'],1))
        x_position_matrix = abs(x_position_matrix-FOV['x_detector_position'])
        y_position_matrix = np.tile(np.arange(FOV['y_len'])[:, np.newaxis],(1,FOV['y_len']))
        y_position_matrix = abs(y_position_matrix - FOV['y_detector_position'])

        depth_of_scene    = (image_matrix/255)*max_depth
        ground_truth = np.reshape(depth_of_scene/max_depth, (FOV['x_len'], FOV['y_len'], 1))
        time_every_point  = (np.sqrt(np.square(depth_of_scene[background_mask])
                             +np.square(x_position_matrix[background_mask])
                             +np.square(y_position_matrix[background_mask]))/3e8)*1e9
        result,_          = np.histogram(time_every_point, bins=bin)
        result = np.reshape(result, (bin, 1))
        arr_matrix[i,:,:]    = result
        tof_data[i, :, :, :] = ground_truth
        if i < 10:
            #保存直方图图像
            plt.hist(time_every_point, bins=bin, color='blue', edgecolor='black')
            plt.savefig('histogram.png')

    arr_matrix = np.array(arr_matrix)
    return arr_matrix,tof_data